
-- -- stack.cl
-- -- cool语言实现任意数据类型的队列

-- -- Node类
-- -- 任意类型的变量和指向写一个节点的指针

class Node inherits Object {
    val : Object;  -- 数据
    next : Node;    -- 指向下一个节点的指针

    construct(x : Object, node : Node) : Node {
        {
            val <- x;
            next <- node;
            self;
        }
    };

    getNext() : Node {
        next
    };

    getVal() : Object {
        val
    };
};

class Stack {
    top : Node;     -- 指向栈顶的指针，默认为void
    size : Int;

    init() : Stack {
        {
            size <- 0;
            self;
        }
    };

    empty() : Bool {
        isvoid top
    };

    stackSize() : Int {
        size
    };

    -- push将一个元素压入栈顶
    push(x : Object) : SELF_TYPE {
        let new_node : Node <- (new Node).construct(x, top) in
        {
            top <- new_node;
            size <- size + 1;
            self;
        }
    };

    -- top获取栈顶元素
    top() : Object {
        if empty() then 
            (new IO).out_string("stack is empty, top error!\n")
        else
            top.getVal()
        fi
    };

    -- pop删除站栈顶元素并返回
    pop() : Object {
        if empty() then 
            (new IO).out_string("stack is empty, pop error!\n")
        else
            let ret : Object <- top.getVal() in
            {
                top <- top.getNext();
                size <- size - 1;
                ret;
            }
        fi
    };

};

class Main inherits IO{
    main():Object {
        let st : Stack <- (new Stack).init() in
        {
            out_string("test stack: \n");
            out_string("push 10, 20, 30\n");
            st.push(10);
            st.push(20);
            st.push(30);
            out_string("\n");

            out_string("stacksize: ");
            out_int(st.stackSize());
            out_string("\n\n");

            -- 2. 测试top与pop
            out_string("get top val, expected result: 30\n");
            out_string("actual result: ");
            case st.top() of
                s : String => out_string(s);
                i : Int => out_int(i);
                o : Object => out_string("Object");
            esac;
            out_string("\n\n");

            out_string("pop twice!\n");
            st.pop();
            st.pop();
            out_string("get top val, expected result: 10\n");
            out_string("actual result: ");
            case st.top() of
                s : String => out_string(s);
                i : Int => out_int(i);
                o : Object => out_string("Object");
            esac;
            out_string("\n");
            out_string("stacksize: ");
            out_int(st.stackSize());
            out_string("\n\n");

            out_string("pop, stack is empty, test top and pop\n");
            st.pop();
            st.pop();
            st.top();

            out_string("\n");
            out_string("test finished!\n");
        }

        
    };
};



